using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Security.Cryptography;
using System.Web.Script.Serialization;
using System.IO;
using System.Globalization;
using System.Runtime.InteropServices;

namespace LanguageInfo.Common.Utilities
{
	/// <summary>
	/// 描述：字符串处理工具类
	/// 作者：路晓阳
	/// 时间：2010-6-1
	/// </summary>
	public static class StringHelper
	{
		private static Regex RegexBr = new Regex(@"(\r\n)", RegexOptions.IgnoreCase);
		private static Regex RegexClearHtmlWhithoutBrPImg = new Regex(@"</?(?!br|/?p|img)[^>]*>", RegexOptions.IgnoreCase);
		private static Regex RegexClearHtmlWhithoutBrP = new Regex(@"</?(?!br|/?p)[^>]*>", RegexOptions.IgnoreCase);
		private static Regex RegexHtmlBr = new Regex(@"<(br\s*/?)[^>]*>", RegexOptions.IgnoreCase);
		private static Regex RegexSqlFilter = new Regex(@"\<|\>|&|\r|\n|\'|\x5c|~|\$|\@|`|!|\*|%|\x5f", RegexOptions.IgnoreCase);
		private static Regex RegexClearFilename = new Regex(@"[\\/:""|*?<>\s]", RegexOptions.IgnoreCase);
		private static Regex RegexEmail = new Regex(@"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$", RegexOptions.IgnoreCase);
		private static Regex RegexIP = new Regex(@"^(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])$");

		/// <summary>
		/// 判断是否为Email
		/// </summary>
		/// <param name="strIn"></param>
		/// <returns></returns>
		public static bool IsEmail(string strIn)
		{
			// Return true if strIn is in valid e-mail format.
			return RegexEmail.IsMatch(strIn);
		}

		/// <summary>
		/// 过滤文件名中的特殊字符包括空格
		/// </summary>
		/// <param name="str"></param>
		/// <returns></returns>
		public static string ClearFilename(string str)
		{
			return RegexClearFilename.Replace(str, string.Empty);
		}


		/// <summary>
		/// 转换HTML代码，将尖括号转换为&lt;形式
		/// </summary>
		/// <param name="exp1">要转换的字符串</param>
		/// <returns>返回过滤后的字符串</returns>
		public static String ToHtmlString(string exp1)
		{
			StringBuilder sb = new StringBuilder(1024);

			var iterator = exp1.GetEnumerator();
			while (iterator.MoveNext())
			{
				switch (iterator.Current)
				{
					case '<':
						sb.Append("&lt;");
						break;
					case '>':
						sb.Append("&gt;");
						break;
					case '\'':
						sb.Append("''");
						break;
					case '"':
						sb.Append("'");
						break;
					case '\n':
						sb.Append("<br/>");
						break;
					case '\r':
						break;
					default:
						sb.Append(iterator.Current);
						break;
				}
			}
			return sb.ToString();
		}

		public static String ToHtmlStringOneBr(string exp1)
		{
			return Regex.Replace(ToHtmlString(exp1), @"(<br>\s*|<br\s*/>\s*)+",
				"<br/>", RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.Multiline);
		}

        /// <summary>
        /// 获得包含中英文字符串的字节长度
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        static public int trueLength(string str)
        {

            // str 字符串
            // return 字符串的字节长度
            int lenTotal = 0;
            int n = str.Length;
            string strWord = "";
            int asc;
            for (int i = 0; i < n; i++)
            {
                strWord = str.Substring(i, 1);
                asc = Convert.ToChar(strWord);
                if (asc < 0 || asc > 127)
                    lenTotal = lenTotal + 2;
                else
                    lenTotal = lenTotal + 1;
            }

            return lenTotal;
        }
		/// <summary>
		/// 过滤脚本字符，使其可以在脚本中使用
		/// </summary>
		/// <param name="exp1"></param>
		/// <returns></returns>
		public static String ScriptStr(string exp1)
		{
			using (StringWriter writer = new StringWriter())
			{
				exp1 = RegexBr.Replace(exp1, "\n");
				StringReader sr = new StringReader(exp1);
				char c;
				int code = sr.Read();
				while (code != -1)
				{
					c = Convert.ToChar(code);
					switch (c)
					{
						case '\t':
							writer.Write(@"\t");
							break;
						case '\n':
							writer.Write(@"\n");
							break;
						case '\r':
							writer.Write(@"\r");
							break;
						case '\f':
							writer.Write(@"\f");
							break;
						case '\b':
							writer.Write(@"\b");
							break;
						case '<':
							writer.Write(@"\u003c");
							break;
						case '>':
							writer.Write(@"\u003e");
							break;
						case '"':
							// only escape if this charater is being used as the delimiter
							//if (delimiter == '"')
							writer.Write(@"\""");
							//else
							//	writer.Write(value);
							break;
						case '\'':
							writer.Write(@"\u0027");
							break;
						case '\\':
							writer.Write(@"\\");
							break;
						default:
							if (c > '\u001f')
								writer.Write(c);
							else
							{
								writer.Write("\\u00");
								int intVal = (int)c;
								writer.Write((char)('0' + (intVal >> 4)));
								intVal &= 0xf;
								writer.Write((char)(intVal < 10 ? '0' + intVal : 'a' + (intVal - 10)));
							}
							break;
					}
					code = sr.Read();
				}
				sr.Close();
				writer.Close();
				sr.Dispose();

				return writer.ToString();
			}
		}

		/// <summary>
		/// 编码字符同js的escape
		/// </summary>
		/// <param name="str"></param>
		/// <returns></returns>
		public static string Escape(string str)
		{
			if (str == null)
				return String.Empty;

			StringBuilder sb = new StringBuilder();

			for (int i = 0; i < str.Length; i++)
			{
				char c = str[i];

				//everything other than the optionally escaped chars _must_ be escaped 
				if (Char.IsLetterOrDigit(c) || c == '-' || c == '_' || c == '/' || c == '\\' || c == '.' || Char.ConvertToUtf32(c.ToString(), 0) > 255)
					sb.Append(c);
				else
					sb.Append(Uri.HexEscape(c));
			}

			return sb.ToString();
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="str"></param>
		/// <returns></returns>
		public static string UnEscape(string str)
		{
			if (str == null)
				return String.Empty;

			StringBuilder sb = new StringBuilder();
			int i = 0;
			while (i != str.Length)
			{
				if (Uri.IsHexEncoding(str, i))
					sb.Append(Uri.HexUnescape(str, ref i));
				else
					sb.Append(str[i++]);
			}

			return sb.ToString();
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="exp1"></param>
		/// <returns></returns>
		public static String ScriptStr(object exp1)
		{
			return ScriptStr(exp1.ToString());
		}
		/// <summary>
		/// 转换HTML代码，将尖括号转换为&lt;形式，但不转换换行符
		/// </summary>
		/// <param name="exp1">要转换的字符串</param>
		/// <returns></returns>
		public static string ToHtmlStringWithoutReturn(string exp1)
		{
			string exp2;
			exp2 = exp1.Replace("<", "&lt;");
			exp2 = exp2.Replace(">", "&gt;");
			exp2 = exp2.Replace("'", "''");
			exp2 = exp2.Replace("  ", "　");
			return exp2;


		}

		/// <summary>
		/// 过滤SQL代码
		/// </summary>
		/// <param name="sql"></param>
		/// <returns></returns>
		public static string SqlStr(string sql)
		{
			return RegexSqlFilter.Replace(sql, string.Empty);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="str"></param>
		/// <returns></returns>
		public static string EnsureSqlStr(string str)
		{
			return str.Replace("'", "''");
		}

		/// <summary>
		/// 转换为保留两位小数的货币
		/// </summary>
		/// <param name="src"></param>
		/// <param name="isZeroEmpty">为0时是否返回空</param>
		/// <returns></returns>
		public static string GetMoney(object src, bool isZeroEmpty)
		{
			float val = 0;

			if (null != src)
				float.TryParse(src.ToString(), out val);
			if (isZeroEmpty && 0 == val)
				return string.Empty;
			else
				return val.ToString("C");
		}

		/// <summary>
		/// 取字符串前length位字符，并是否在末尾加省略号
		/// </summary>
		/// <param name="src"></param>
		/// <param name="length"></param>
		/// <param name="addDots">是否加省略号</param>
		/// <returns></returns>
		public static string GetLeft(string src, int length, bool addDots)
		{
			if (string.IsNullOrEmpty(src)) return string.Empty;

			if (src.Length > length)
			{
				src = string.Concat(src.Substring(0, addDots ? length - 1 : length), addDots ? "..." : string.Empty);
			}
			return src;
		}

		/// <summary>
		/// 将ip最后一段转换为*
		/// </summary>
		/// <param name="ip"></param>
		/// <returns></returns>
		public static string EncodeIP(string ip)
		{
			return string.Concat(ip.Substring(0, ip.LastIndexOf('.') + 1), "*");
		}

		public static string ClearHtml(string htmlString, string htmlPlaceHolder)
		{
			if (string.IsNullOrEmpty(htmlString)) return string.Empty;
			const string pattern = @"<(.|\n)*?>";
			return Regex.Replace(htmlString, pattern, htmlPlaceHolder);
		}

		public static string ClearHtml(string htmlString)
		{
			return ClearHtml(htmlString, string.Empty);
		}

		/// <summary>
		/// Strips all HTML tags from a string and replaces the tags with the specified replacement
		/// </summary>
		/// <param name="htmlString">The HTML string.</param>
		/// <param name="htmlPlaceHolder">The HTML place holder.</param>
		/// <returns></returns>
		public static string StripHTML(string htmlString, string htmlPlaceHolder)
		{
			string sOut = ClearHtml(htmlString, htmlPlaceHolder);
			sOut = sOut.Replace("&nbsp;", String.Empty);
			sOut = sOut.Replace("&amp;", "&");
			sOut = sOut.Replace("&gt;", ">");
			sOut = sOut.Replace("&lt;", "<");
			return sOut;
		}

		/// <summary>
		/// 获取参数的首个不为null的对象
		/// </summary>
		/// <param name="objs"></param>
		/// <returns></returns>
		public static object GetFirstNotNullObject(params object[] objs)
		{
			foreach (object obj in objs)
			{
				if (!(null == obj || DBNull.Value == obj))
				{
					return obj;
				}
			}
			return null;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="g"></param>
		/// <returns></returns>
		public static string GetGenderString(object g)
		{
			switch ((g ?? "").ToString())
			{
				case "1":
					return "男";
				case "2":
					return "女";
				default:
					return "";
			}
		}

		/// <summary>
		/// 判断指定字符串在指定字符串数组中的位置
		/// </summary>
		/// <param name="strSearch">字符串</param>
		/// <param name="stringArray">字符串数组</param>
		/// <param name="caseInsensetive">是否不区分大小写, true为不区分, false为区分</param>
		/// <returns>字符串在指定字符串数组中的位置, 如不存在则返回-1</returns>
		public static int GetInArrayID(string strSearch, string[] stringArray, bool caseInsensetive)
		{
			for (int i = 0; i < stringArray.Length; i++)
			{
				if (caseInsensetive)
				{
					if (strSearch.ToLower() == stringArray[i].ToLower())
					{
						return i;
					}
				}
				else
				{
					if (strSearch == stringArray[i])
					{
						return i;
					}
				}

			}
			return -1;
		}


		/// <summary>
		/// 判断指定字符串在指定字符串数组中的位置
		/// </summary>
		/// <param name="strSearch">字符串</param>
		/// <param name="stringArray">字符串数组</param>
		/// <returns>字符串在指定字符串数组中的位置, 如不存在则返回-1</returns>		
		public static int GetInArrayID(string strSearch, string[] stringArray)
		{
			return GetInArrayID(strSearch, stringArray, true);
		}

		/// <summary>
		/// 判断指定字符串是否属于指定字符串数组中的一个元素
		/// </summary>
		/// <param name="strSearch">字符串</param>
		/// <param name="stringArray">字符串数组</param>
		/// <param name="caseInsensetive">是否不区分大小写, true为不区分, false为区分</param>
		/// <returns>判断结果</returns>
		public static bool InArray(string strSearch, string[] stringArray, bool caseInsensetive)
		{
			return GetInArrayID(strSearch, stringArray, caseInsensetive) >= 0;
		}

		/// <summary>
		/// 判断指定字符串是否属于指定字符串数组中的一个元素
		/// </summary>
		/// <param name="str">字符串</param>
		/// <param name="stringarray">字符串数组</param>
		/// <returns>判断结果</returns>
		public static bool InArray(string str, string[] stringarray)
		{
			return InArray(str, stringarray, false);
		}

		/// <summary>
		/// 判断指定字符串是否属于指定字符串数组中的一个元素
		/// </summary>
		/// <param name="str">字符串</param>
		/// <param name="stringarray">内部以逗号分割单词的字符串</param>
		/// <returns>判断结果</returns>
		public static bool InArray(string str, string stringarray)
		{
			return InArray(str, SplitString(stringarray, ","), false);
		}

		/// <summary>
		/// 判断指定字符串是否属于指定字符串数组中的一个元素
		/// </summary>
		/// <param name="str">字符串</param>
		/// <param name="stringarray">内部以逗号分割单词的字符串</param>
		/// <param name="strsplit">分割字符串</param>
		/// <returns>判断结果</returns>
		public static bool InArray(string str, string stringarray, string strsplit)
		{
			return InArray(str, SplitString(stringarray, strsplit), false);
		}

		/// <summary>
		/// 判断指定字符串是否属于指定字符串数组中的一个元素
		/// </summary>
		/// <param name="str">字符串</param>
		/// <param name="stringarray">内部以逗号分割单词的字符串</param>
		/// <param name="strsplit">分割字符串</param>
		/// <param name="caseInsensetive">是否不区分大小写, true为不区分, false为区分</param>
		/// <returns>判断结果</returns>
		public static bool InArray(string str, string stringarray, string strsplit, bool caseInsensetive)
		{
			return InArray(str, SplitString(stringarray, strsplit), caseInsensetive);
		}

		/// <summary>
		/// 分割字符串
		/// </summary>
		public static string[] SplitString(string strContent, string strSplit)
		{
			if (strContent.IndexOf(strSplit) < 0)
			{
				string[] tmp = { strContent };
				return tmp;
			}
			return Regex.Split(strContent, Regex.Escape(strSplit), RegexOptions.IgnoreCase);
		}

		/// <summary>
		/// 分割字符串
		/// </summary>
		/// <returns></returns>
		public static string[] SplitString(string strContent, string strSplit, int p_3)
		{
			string[] result = new string[p_3];

			string[] splited = SplitString(strContent, strSplit);

			for (int i = 0; i < p_3; i++)
			{
				if (i < splited.Length)
					result[i] = splited[i];
				else
					result[i] = string.Empty;
			}

			return result;
		}

		/// <summary>
		/// 清除给定字符串中的回车及换行符
		/// </summary>
		/// <param name="str">要清除的字符串</param>
		/// <returns>清除后返回的字符串</returns>
		public static string ClearBR(string str)
		{
			//Regex r = null;
			Match m = null;

			//r = new Regex(@"(\r\n)",RegexOptions.IgnoreCase);
			for (m = RegexBr.Match(str); m.Success; m = m.NextMatch())
			{
				str = str.Replace(m.Groups[0].ToString(), "");
			}


			return str;
		}

		/// <summary>
		/// 判断文件名是否为浏览器可以直接显示的图片文件名
		/// </summary>
		/// <param name="filename">文件名</param>
		/// <returns>是否可以直接显示</returns>
		public static bool IsImgFilename(string filename)
		{
			filename = filename.Trim();
			if (filename.EndsWith(".") || filename.IndexOf(".") == -1)
			{
				return false;
			}
			string extname = filename.Substring(filename.LastIndexOf(".") + 1).ToLower();
			return (extname == "jpg" || extname == "jpeg" || extname == "png" || extname == "bmp" || extname == "gif");
		}

		/// <summary>
		/// MD5函数
		/// </summary>
		/// <param name="str">原始字符串</param>
		/// <returns>MD5结果</returns>
		public static string MD5(string str)
		{
			//Hash hash = new Hash(Hash.Provider.MD5);
			//Data d = new Data(str);
			//return hash.Calculate(d).Hex;

			byte[] b = Encoding.Default.GetBytes(str);
			b = new MD5CryptoServiceProvider().ComputeHash(b);
			Stack<string> ret = new Stack<string>(b.Length);
			for (int i = b.Length - 1; i >= 0; i--)
				ret.Push(b[i].ToString("X").PadLeft(2, '0'));

			return string.Join(string.Empty, ret.ToArray());
		}

		/// <summary>
		/// SHA256函数
		/// </summary>
		/// /// <param name="str">原始字符串</param>
		/// <returns>SHA256结果</returns>
		public static string SHA256(string str)
		{
			byte[] SHA256Data = Encoding.UTF8.GetBytes(str);
			SHA256Managed Sha256 = new SHA256Managed();
			byte[] Result = Sha256.ComputeHash(SHA256Data);
			return Convert.ToBase64String(Result);  //返回长度为44字节的字符串
		}

		/// <summary>
		/// 从HTML中获取文本,保留br,p,img
		/// </summary>
		/// <param name="HTML"></param>
		/// <returns></returns>
		public static string GetTextFromHTMLWithImg(string HTML)
		{
			return RegexClearHtmlWhithoutBrPImg.Replace(HTML, "");
		}

		/// <summary>
		/// 从HTML中获取文本,保留br,p
		/// </summary>
		/// <param name="HTML"></param>
		/// <returns></returns>
		public static string GetTextFromHTML(string HTML)
		{
			return RegexClearHtmlWhithoutBrP.Replace(HTML, "");
		}


		/// <summary>
		/// 格式化成文件大小显示的方式
		/// </summary>
		/// <param name="size"></param>
		/// <returns></returns>
		public static string FileSizeFormat(long size)
		{
			long kilobyte = 1024;
			long megabyte = 1024 * kilobyte;
			long gigabyte = 1024 * megabyte;
			long terabyte = 1024 * gigabyte;

			if (size > terabyte) return (size / terabyte).ToString("0.00 TB");
			else if (size > gigabyte) return (size / gigabyte).ToString("0.00 GB");
			else if (size > megabyte) return (size / megabyte).ToString("0.00 MB");
			else if (size > kilobyte) return (size / kilobyte).ToString("0.00 KB");
			else return size + " Bytes";
		}

		/// <summary>
		/// 产生验证码
		/// </summary>
		/// <param name="len">长度</param>
		/// <returns>验证码</returns>
		public static string CreateAuthStr(int len)
		{
			int number;
			//StringBuilder checkCode = new StringBuilder();
			Stack<char> checkCode = new Stack<char>(len);
			Random random = new Random();

			for (int i = 0; i < len; i++)
			{
				number = random.Next();
				if (number % 2 == 0)
				{
					checkCode.Push((char)('0' + (char)(number % 10)));
				}
				else
				{
					checkCode.Push((char)('A' + (char)(number % 26)));
				}

			}

			return new string(checkCode.ToArray());
		}

		/// <summary>
		/// 获取第一个匹配的值
		/// </summary>
		/// <param name="html"></param>
		/// <param name="regexPattern"></param>
		/// <param name="groupName"></param>
		/// <returns></returns>
		public static string GetMatchValue(string input, string regexPattern, string groupName)
		{
			var val = string.Empty;
			var m = Regex.Match(input, regexPattern, RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline);
			if (m.Success && m.Groups[1].Success)
				if (string.IsNullOrEmpty(groupName))
					val = m.Groups[1].Value;
				else
					val = m.Groups[groupName].Value;

			return val;
		}

		/// <summary>
		/// 获取第一个匹配的值
		/// </summary>
		/// <param name="html"></param>
		/// <param name="regexPattern"></param>
		public static string GetMatchValue(string input, string regexPattern)
		{
			return GetMatchValue(input, regexPattern, null);
		}


		#region 簡繁轉換
		internal const int LOCALE_SYSTEM_DEFAULT = 0x0800;
		internal const int LCMAP_SIMPLIFIED_CHINESE = 0x02000000;
		internal const int LCMAP_TRADITIONAL_CHINESE = 0x04000000;

		/// <summary> 
		/// 使用OS的kernel.dll做為簡繁轉換工具，只要有裝OS就可以使用，不用額外引用dll，但只能做逐字轉換，無法進行詞意的轉換 
		/// <para>所以無法將電腦轉成計算機</para> 
		/// </summary> 
		[DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
		internal static extern int LCMapString(int Locale, int dwMapFlags, string lpSrcStr, int cchSrc, [Out] string lpDestStr, int cchDest);

		/// <summary> 
		/// 繁體轉簡體 
		/// </summary> 
		/// <param name="pSource">要轉換的繁體字：體</param> 
		/// <returns>轉換後的簡體字：体</returns> 
		public static string Traditional2Simplified(string pSource)
		{
			String tTarget = new String(' ', pSource.Length);
			int tReturn = LCMapString(LOCALE_SYSTEM_DEFAULT, LCMAP_SIMPLIFIED_CHINESE, pSource, pSource.Length, tTarget, pSource.Length);
			return tTarget;
		}

        /// <summary>
        /// 繁体转换简体
        /// </summary>
        /// <param name="strSource"></param>
        /// <returns></returns>
        public static string TraditionConvToSimplified(string strSource)
        {
            return Microsoft.VisualBasic.Strings.StrConv(strSource, Microsoft.VisualBasic.VbStrConv.SimplifiedChinese, 1033);
        }

        /// <summary>
        /// 简体转换繁体
        /// </summary>
        /// <param name="strSource"></param>
        /// <returns></returns>
        public static string SimplifiedConvToTraditional(string strSource)
        {
            return Microsoft.VisualBasic.Strings.StrConv(strSource, Microsoft.VisualBasic.VbStrConv.TraditionalChinese, 1033);
        }

		/// <summary> 
		/// 簡體轉繁體 
		/// </summary> 
		/// <param name="pSource">要轉換的繁體字：体</param> 
		/// <returns>轉換後的簡體字：體</returns> 
		public static string Simplified2Traditional(string pSource)
		{
			String tTarget = new String(' ', pSource.Length);
			int tReturn = LCMapString(LOCALE_SYSTEM_DEFAULT, LCMAP_TRADITIONAL_CHINESE, pSource, pSource.Length, tTarget, pSource.Length);
			return tTarget;
		}
		#endregion


		/// <summary>
		/// 检测IP地址正常性
		/// </summary>
		/// <param name="str"></param>
		/// <returns></returns>
		public static bool IsIp(string str)
		{
			return RegexIP.IsMatch(str);
		}

        public static string FormatWeek(int week)
        {
            if (week.ToString().Length == 1)
                return  "0"+ week.ToString();
            else
                return week.ToString();

        }

        public static string SubString(object val, int lengh)
        {
            string str = val.ToString();

            if (str.Length > lengh)
                return str.Substring(0, lengh);
            else
                return str;
        }
	}
}
